#include <cstdio>

#include "ConfigGenerator.h"

#include "utils.h"

session_mgr::ConfigGenerator::ConfigGenerator():
appNode(),
windowWidth(0),
windowHeight(0),
bufferWidth(0),
bufferHeight(0),
viewWidth(0),
viewHeight(0),
viewDepth(0)
{
    appNode.ipv4addr = 0;
    appNode.port = 0;
    appNode.card_count = 1;
}

bool session_mgr::ConfigGenerator::hasOption(const std::string& key)
{
    return
    key == "window" ||
    key == "buffer" ||
    key == "view" ||
    key == "host" ||
    key == "port" ||
    doHasOption(key);
}

bool session_mgr::ConfigGenerator::setOption(const std::string& key, const std::string& value)
{
    if(key == "window")
        return std::sscanf(value.c_str(), "%u x %u", &windowWidth, &windowHeight) == 2;
    else if(key == "buffer")
        return std::sscanf(value.c_str(), "%u x %u", &bufferWidth, &bufferHeight) == 2;
    else if(key == "view")
        return std::sscanf(value.c_str(), "%lf x %lf x %lf", &viewWidth, &viewHeight, &viewDepth) == 3;
    else if(key == "host")
    {
        unsigned a, b, c, d;
        if(
            std::sscanf(value.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) != 4 ||
            a > 255 ||
            b > 255 ||
            c > 255 ||
            d > 255
        )
            return false;
        appNode.ipv4addr = addr(a, b, c, d);
        return true;
    }
    else if(key == "port")
    {
        unsigned port;
        if(std::sscanf(value.c_str(), "%u", &port) != 1 || port > 65535)
            return false;
        appNode.port = port;
        return true;
    }
    else
        return doSetOption(key, value);
}

bool session_mgr::ConfigGenerator::ready(std::string* errorMessage)
{
    if(errorMessage == NULL)
        return defaultCheck(NULL);
    else
    {
        std::string missing;
        if(defaultCheck(&missing))
            return true;
        else
        {
            *errorMessage = "Option \"" + missing + "\" is either missing or invalid.";
            return false;
        }
    }
}

std::string session_mgr::ConfigGenerator::getFormat(const std::string& key)
{
    if(key == "window")
        return "%u x %u";
    else if(key == "buffer")
        return "%u x %u";
    else if(key == "view")
        return "%lf x %lf x %lf";
    else if(key == "host")
        return "%u.%u.%u.%u";
    else if(key == "port")
        return "%u";
    else
        return doGetFormat(key);
}

bool session_mgr::ConfigGenerator::doHasOption(const std::string&)
{
    return false;
}

bool session_mgr::ConfigGenerator::doSetOption(const std::string&, const std::string&)
{
    return false;
}

std::string session_mgr::ConfigGenerator::doGetFormat(const std::string&)
{
    return std::string();
}

static inline void writeNonNull(std::string *dst, char const* src)
{
    if(dst)
        *dst = src;
}

bool session_mgr::ConfigGenerator::defaultCheck(std::string* missingOption)
{
    if(appNode.ipv4addr == 0)
        writeNonNull(missingOption, "host");
    else if(appNode.port == 0)
        writeNonNull(missingOption, "port");
    else if(windowWidth == 0 || windowHeight == 0)
        writeNonNull(missingOption, "window");
    else if(bufferWidth == 0 || bufferHeight == 0)
        writeNonNull(missingOption, "buffer");
    else if(viewWidth == 0 || viewHeight == 0 || viewDepth == 0)
        writeNonNull(missingOption, "view");
    else
        return true;
    return false;
}
